package hall
{
	import com.gs.utils.Logger;
	
	import commonlib.DGroupInfoItem;
	import commonlib.DMyInfo;
	import commonlib.DRoomInfo;
	import commonlib.L;
	import commonlib.Utility;
	
	import config.DConfig;
	import config.DHallCfg;
	
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.utils.setTimeout;
	
	import game.DFqzs;
	
	import net.DNetworkCenter;
	import net.DNetworkGame;
	import net.DSocket;
	import net.DSocketEvent;
	import net.IDBufNetwork;
	import net.event.DDataEvent;
	import net.event.DNetworkCenterEvent;
	import net.event.DNetworkGameEvent;
	import net.event.DUIHallEvent;
	
	import starling.display.Sprite;

	public class DHall extends Sprite
	{
		private var m_logger:Logger;
		private var m_gcPtr:IDBufNetwork;			//游戏中心网络指针
		private var m_gsPtr:IDBufNetwork;			//游戏服务器网络指针
		private var m_gcProcessor:DNetworkCenter; 	//游戏服务器网络处理
		private var m_gsProcessor:DNetworkGame;   	//大厅网络处理
		private var m_loopTimerToken:int = 0;
		private var m_loopptr:IDBufNetwork = new DSocket();
		
		private var m_ui:DUIHall;
		private var m_myInfo:DMyInfo;				//个人信息		
		private var m_currLanguage:String = L.zh_CN;
		
		private var m_currScene:String = "";
		private var m_currGameName:String = "";
		private var m_serverTime:Number;
		private var m_currGroupInfo:DGroupInfoItem;
		private var m_gameObject:DFqzs;
		
		private var m_grouplist:Array = [];		//分区列表
		//存了一串函数。预加载的时候，有一些资源是没准备好的，所以相关操作都暂时先丢这里。
		private var m_queueAry:Vector.<Function> = new Vector.<Function>();
		//是否预加载完成。用于onUILoadOK时，决定是否执行上面那一串函数
		private var m_bPreloginOK:Boolean = false;				
		//是否在预加载完成后执行缓存队列中函数
		private var m_bDoQueueAfterPrelogin:Boolean = false;		
		//游戏是否已经登陆过，在第一登陆成功后为true，用于房间切换
		private var m_bGameHaveLogined:Boolean = false;	
		
		public function DHall()
		{
			m_logger = Logger.getInstance(DHall);
			m_logger.info("init");
			m_gcPtr = new DSocket();
			m_gsPtr = new DSocket();
			m_myInfo = new DMyInfo();
			
			m_ui = new DUIHall();
			this.addChild(m_ui);
			
			doPreLogin();
		}
		
		//------------------------------ 内部方法 ------------------------------
		private function doPreLogin():void
		{
			//初始化gamecenter网络连接
			m_gcPtr.connect(DConfig.GAME_HOST, DConfig.PORT);
			m_logger.info("attempt to connect gamecenter..." + DConfig.GAME_HOST + ":" + DConfig.PORT);
			m_gcPtr.addEventListener(DSocketEvent.CONNECT, net_onGameCenterConnectedSucceed);
			m_gcPtr.addEventListener(DSocketEvent.ERROR, net_onGameCenterConnectedError);
		}
		
		private function finishPrelogin():void
		{
			m_bPreloginOK = true;
			if (m_bDoQueueAfterPrelogin) 
			{
				for each(var f:Function in m_queueAry) f();
			}
		}
		
		private function initUiEvent(type:String):void
		{
			m_logger.info("initUiEvent() type:" + type);
			if(m_ui)
			{
				m_ui.addEventListener(DUIHallEvent.ON_UI_SELECT_GAME, onSelectGame);
				m_ui.addEventListener(DUIHallEvent.ON_UI_BACK_TO_HALL, onReleaseGame);
			}
		}
		
		private function connectGameServer():void
		{
			if (m_gsPtr.isConnected) return;
			
			var groupInfo:DGroupInfoItem = m_grouplist[DConfig.strDefaultGame][0];					
			var ip:String = groupInfo["ip"];
			var port:int = groupInfo["port"];
			m_logger.info("正在进入游戏逻辑服务器：" + ip + ":" + port);		
						
			m_currGroupInfo = groupInfo;
			m_gsPtr.connect(ip, port);
			if (!m_gsPtr.hasEventListener(DSocketEvent.CONNECT))	
			{
				m_gsPtr.addEventListener(DSocketEvent.CONNECT, net_onGameServerConnectedSucceed);			
			}
			if (!m_gsPtr.hasEventListener(DSocketEvent.ERROR))
			{
				m_gsPtr.addEventListener(DSocketEvent.ERROR, net_onGameServerConnectedError);
			}			
			
		}
		
		//------------------------------ 事件处理 ------------------------------
		private function net_onGameCenterConnectedSucceed(e:DSocketEvent):void
		{
			m_gcPtr.removeEventListener(DSocketEvent.CONNECT, net_onGameCenterConnectedSucceed);
			m_logger.info("connect success, send login info..." + DConfig.strUser + ":" + DConfig.strKey);
			m_gcPtr.addEventListener(DSocketEvent.CLOSE, net_onGameCenterConnectedClose);
			
			m_myInfo.strUser = DConfig.strUser;
			m_myInfo.strKey = DConfig.strKey;
			
			m_gcProcessor = new DNetworkCenter(m_gcPtr);	
			m_gcProcessor.addEventListener(DNetworkCenterEvent.ON_RECV_GROUP_INFO, gc_onRecvGroupInfo);
			m_gcProcessor.addEventListener(DNetworkCenterEvent.ON_RECV_LOGIN_RESULT, gc_onRecvGameCenterLoginResult);
			m_gcProcessor.addEventListener(DNetworkCenterEvent.ON_RECV_DISABLE_ACCOUNT, gc_onRecvDisableAccount);
			
			m_gcProcessor.sendGetAreaInfo("dznew|ddz|zjh|mj|soha|tlj|sdh|pdk|dz2|lzdz|cdd|hldz|tex");  //TODO
			m_gcProcessor.sendLoginInfo(DConfig.strUser, DConfig.strKey);
		}
		
		private function net_onGameCenterConnectedError(e:DSocketEvent):void
		{
			m_gcPtr.removeEventListener(DSocketEvent.ERROR, net_onGameCenterConnectedError);
			m_logger.error(L.getL(L.connect_error, m_currLanguage));
		}
		
		private function net_onGameCenterConnectedClose(e:DSocketEvent):void
		{
			m_logger.info("您已与服务器断开链接，请退出游戏后再次进入游戏。");
		}
		
		private function net_onGameServerConnectedSucceed(e:DSocketEvent):void
		{
			m_gsPtr.removeEventListener(DSocketEvent.CONNECT, net_onGameServerConnectedSucceed);
			m_logger.info("进入游戏逻辑服务器成功");
			m_gsProcessor = new DNetworkGame(m_gsPtr);
			m_gsProcessor.addEventListener(DNetworkGame.CMD_LOGIN_RESULT,gs_onRecvGameServerLoginResult);
			
			
			m_gsProcessor.addEventListener(DNetworkGame.CMD_ROOM_LIST, gs_onRecvRoomList);
			m_gsProcessor.addEventListener(DNetworkGame.CMD_ENTER_ROOM, gs_onRecvEnterRoom);
			m_gsProcessor.addEventListener(DNetworkGame.CMD_ROOM_PEOPLE_NUM, gs_onRecvPeopleNum);
			/*
			
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_CAN_NOT_TOROOM, ns_onRecvCanNotIntoRoom);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_SERVER_ERROR, ns_onRecvServerError);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_RESTRICT_LOGIN, ns_onRecvRestrictLogin);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_GM_KICK, ns_onRecvGMKick);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_WATCH_ERROR, ns_onRecvWatchError); //进入观战失败
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_SITDOWN_RESULT, ns_onSitDwonResult);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_USER_HALL_GAMEINFO, ns_onRecvUserHallInfo);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_USER_GAME_GAMEINFO, ns_onRecvUserGameInfo);			
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_MY_INFO, ns_onRecvMyInfo);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_GROUP_INFO, ns_onRecvGroupInfo);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_ACTIVE_FACE, ns_onActionFace);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_CHANGE_FACE_OK, ns_onChangeFaceOk);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_SELECT_FACE_OK, ns_onSelectFaceResult);
			//m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_CURPAGEROOM_LIST, ns_onRecvCurrentPage);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_DESK_USERLIST, ns_onRecvDeskUserList);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_CURPAGEROOM_CHANGED, ns_onRecvDeskListChanged);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_CHANGE_GOLD, ns_onRecvGoldChange);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_LOW_GOLD, ns_onRecvLowGold);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_INTEGRAL_JIESUAN, ns_onIntegralJieusuan);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_SORT_LIST, ns_onRecvSortList);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_USER_ADD, ns_onRecvUserAdd);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_USER_DEL, ns_onRecvUserDel);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_STUDY_PRIZE, ns_onRecvShowStudyOK);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_TEX_RECV_FEEDBACK_CAN_USE, ms_onRecvFeedBackCanUse);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_TEX_RECV_SHOW_CHONGZHI, ns_onRecvShowChongzhiPanel);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_TEX_RECV_PRIVILEGE_CHECK, onRecvPrivilegeCheck);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_CHOOSE_SHOW, nc_onRecvChooseShow);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_UPDATE_NICK_INFO, nc_onRecvUpdateNickResult);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_SPEAKER_BROADCAST, nc_onRecvSpeakerBroadcast);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_SPEAKER_NUM, nc_onRecvSpeakerNum);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_CHECK_IP, nc_onRecvCheckIp);			
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_UNLOCK, nc_onRecvUnlock); 
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_REFRESH_PROPS_COUNT, nc_onRecvRefreshPropsCount);				
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_RECV_UPDATE_GOLD, nc_onRecvUpdateGold);			
			
			//-----------------------------登陆送钱-----------------------//
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_TEX_LOGIN_SHOW_DAY_GOLD, onRecvLoginShowGiveGold);
			m_gsProcessor.addEventListener(DNetworkGameEvent.ON_TEX_RECV_LOGIN_GIVE, onRecvLoginGiveGold);		
			*/
			m_gsProcessor.sendRequestLoginGame(m_myInfo.userId, DConfig.strKey);
			
		}
		
		private function net_onGameServerConnectedError(e:DSocketEvent):void
		{
			m_gsPtr.removeEventListener(DSocketEvent.ERROR, net_onGameCenterConnectedError);
			m_logger.error(L.getL(L.connect_error, m_currLanguage));
		}
		
		/**
		 *
		 * 接收分区信息回调
		 */
		private function gc_onRecvGroupInfo(e:DNetworkCenterEvent):void
		{
			m_logger.info("收到 groupInfo list");
			for (var key:String in e.data as Array) 
			{
				if (m_grouplist[key] == null) m_grouplist[key] = [];				
				for each(var item:DGroupInfoItem in e.data[key]) 
				{
					m_grouplist[key].push(item);
				}
			}
			
			for (var gameName:String in m_grouplist)
			{
				m_grouplist[gameName] = Utility.sortAsc(m_grouplist[gameName], "groupid");
				
				for (var i:int = 0; i < m_grouplist[gameName].length; i++)				
				{
					m_grouplist[gameName][i].sourceindex = i;
				}
			}
			
			connectGameServer();
		}

		/**
		 *
		 * 接受登录信息回调
		 */
		private function gc_onRecvGameCenterLoginResult(e:DNetworkCenterEvent):void
		{
			m_gcProcessor.removeEventListener(DNetworkCenterEvent.ON_RECV_LOGIN_RESULT, gc_onRecvGameCenterLoginResult);
			m_logger.info("登陆GameCenter结果：" + e.data["code"]);
			if (e.data["lastroomname"] != "")	DConfig.strDefaultGame 	= e.data["lastroomname"];
			DConfig.strKey = e.data["gamekey"];		//登陆换Key
			m_loopTimerToken = e.data["userid"];
			m_myInfo.md5 = e.data["md5"];
			m_myInfo.userId = e.data["userid"];
			
			var loopTimer:Timer = new Timer(2 * 60 * 1000, 0);
			loopTimer.addEventListener(TimerEvent.TIMER, onLoopTimer)
			loopTimer.start();
			
			//正常或重登录用户
			if (e.data["code"] == DHallCfg.LOGINOK || e.data["code"] == 2)   
			{	
				m_queueAry.push(
					function():void
					{
						initUiEvent(DConfig.EVENT_ADD);
						enterGame(DConfig.strDefaultGame);		
						m_gcPtr.close();						
					}
				);
			}
			else if (e.data["code"] == -3) //服务器异常
			{
				m_queueAry.push(
					function():void {	m_logger.error(L.getL(L.connect_error, m_currLanguage));}
				);			
			}
			else //可能是yy服务器验证出错
			{
				m_queueAry.push(
					function():void {	m_logger.error("用户验证出错，服务器返回状态:" + e.data["code"].toString());}
				);				
			}
			
			finishPrelogin();
		}
		
		/**
		 * 收到帐号被封
		 * @param e
		 */
		private function gc_onRecvDisableAccount(e:DNetworkCenterEvent):void
		{
			
			if (e.data["status"] == 0)
			{
				m_logger.error("您的帐号已被永久封停，如果任何疑问请联系达人游戏客服。");				
			}
			else
			{
				m_logger.error("您的帐号已被封停，如果任何疑问请联系达人游戏客服。");				
			}
		}
		
		private function onLoopTimer(e:Event):void
		{
			if (m_loopptr.isConnected) return;
			if (m_gcPtr.isConnected) return;
			if (m_gsPtr.isConnected) return;
			m_loopptr.addEventListener(DSocketEvent.CONNECT, function(e:Event):void
			{
				new DNetworkCenter(m_loopptr).sendToken(m_loopTimerToken);
				m_loopptr.close();
			});
			m_loopptr.addEventListener(DSocketEvent.ERROR, function(e:Event):void { m_loopptr.close(); } );			
			m_loopptr.connect(DConfig.GAME_HOST, DConfig.PORT);
		}
		
		private function gs_onRecvGameServerLoginResult(e:DNetworkGameEvent):void
		{			
			m_logger.info("gs_onRecvGameServerLoginResult() code:" + e.data["code"]);
			var strMsg:String = "";
			if (e.data["code"] == DHallCfg.LOGINOK || e.data["code"] == 2)
			{	
				if (m_bGameHaveLogined == false)				
				{
					m_serverTime = Number(e.data.ostime);				
					m_bGameHaveLogined = true;		//设置游戏已经加载成功，用于切换房间用
				}				
				
				dispatchEventWith(DDataEvent.GAME_LOGIN_OK, false, { game:m_currGameName });
			}
			else if(e.data["code"] == -101)
			{
				m_logger.info("进入游戏失败，可能有同名帐号正在游戏，请退出游戏再试！");
			}
			else if(e.data["code"] == -102)
			{	
				m_logger.info("您已经在一个房间打牌，请完成牌局");
			}
			else 
			{
				m_logger.info("登陆游戏服务器失败 错误码：" + e.data["code"]);	
			}
		}
		
		//游戏房间列表信息
		private function gs_onRecvRoomList(e:DNetworkGameEvent):void
		{
			DRoomInfo.getThis().setRoomList(e.data.list);
			//m_ui.refreshRoomList();
		}
		
		//收到进入房间结果
		private function gs_onRecvEnterRoom(e:DNetworkGameEvent):void
		{
			DRoomInfo.getThis().currRoomid = e.data.roomid;	//记录当前进入的房间ID
			var gameId:int = DRoomInfo.getThis().getCurrRoomInfo().gameid;
			m_currGameName = DConfig.ARY_GAME_NAME[gameId];
			
			var data:Object = { };
			data[e.data.roomid] = { 
				defaultValue:e.data.defaultValue, minValue:e.data.minValue, maxValue:e.data.maxValue, numPeople:e.data.numPeople
			};			
			DRoomInfo.getThis().setDuihuanDatas(data);	//更新兌換信息
			//1成功，-1失败，-2等级不够 -3金币不够 -4人数满
			var nResult:int = e.data.nResult;
			var msg:String = "";
			
			if (nResult == -1) 
			{
				msg = "对不起，進入房間失敗[錯誤代碼：" + nResult + "]！";
			}
			else if (nResult  == -2) 
			{
				msg = "对不起，您的等級不夠！";
			}
			if (nResult == -3)
			{
				msg = "对不起，您的金幣不足！";
			}
			else if (nResult == -4) 
			{
				msg = "对不起，此房間已滿！";
			}
			
			if (msg != "")
			{
//				m_ui.showMessageBox(msg, "", Language.res_OK);
				m_logger.info(msg);
				return;
			}
//			loadGameUI(m_currentGameName);
		}
				
		//房間人數
		private function gs_onRecvPeopleNum(e:DNetworkGameEvent):void
		{
			DRoomInfo.getThis().setRoomInfo(e.data.roomId, e.data);
			m_ui.refreshRoomList();
		}
		
		private function onSelectGame(e:DUIHallEvent):void 
		{
//			m_currentGameName = e.data[0].gamename;
			var roominfo:Object = e.data[0].roominfo;
			m_gsProcessor.requestEnterRoom(roominfo ? roominfo.id : -2);	//-2表示讓服務端自動分配遊戲和房間
		}
		
		private function onReleaseGame(e:DUIHallEvent):void 
		{
			m_currScene = DConfig.SCENE_HALL;	//场景切换
			if (!m_gameObject) return;
			m_gameObject.dispose();
			m_gameObject = null;
//			dispatchEvent(new DDataEvent("GAME_RELEASE", { gameId:DConfig.ARY_GAME_ID[m_currentGameName], gameName:m_currentGameName }));	
//			DRoomInfo.getInstance().currRoomid = 0;
			m_gsProcessor.requestBackToHall();
		}
		
		//------------------------------ 外部接口 ------------------------------
		
		public function enterGame(name:String):void
		{
			m_currGameName = name;
			
			if (!m_grouplist[m_currGameName]) m_grouplist[m_currGameName] = new Vector.<DGroupInfoItem>();
			var groupInfo:DGroupInfoItem = m_grouplist[m_currGameName][0];
			var groupId:int = groupInfo.groupid;
	
			//m_ui.showRoomList(m_grouplist[m_currGameName], roomid , this.m_currentGameName);	
		}
			
		public function getMyInfo():DMyInfo
		{
			return m_myInfo;
		}

		public function get currLanguage():String
		{
			return m_currLanguage;
		}
		
		
	}
} 